using System;
using System.Data;
using System.Text;
using System.Collections;
using RNChessBoardCommonTypes;
//---------------------------------------------------------------------------//
//																			 //
//			r  n  C  h  e  s  s  B  o  a  r  d  C  o  n  t  r  o  l			 //
//			=======================================================			 //
//						  (c) 2003 Chris R. Chapman							 //
//																			 //
//	Version:		1.0	Full												 //
//  Date:			May 2003												 //
//  Author:			Chris R. Chapman (chris@chapmanconsulting.ca)			 //
//  Description:	A chessboard GUI written in 100% .Net/C#, featuring		 //
//					a resizable board with adjustable colors and configurable//
//					images for pieces, as well as events for capturing player//
//					movement and illegal moves.								 //
//																			 //
//																			 //
// LICENSING:		Can be freely distributed and used as long as the		 //
//					following criteria are met:								 //
//																			 //
//					1) All copyright notices are kept intact;				 //
//					2) Product is not for commercial resale;				 //
//					3) Product is NOT used in conjunction with ANY GPLed or  //
//					   FSF software.  I cannot abide by their philosophies.  //
//					4) Credit for the control to me is made in some			 //
//					   conspicuous fashion, like an About box.				 //
//---------------------------------------------------------------------------//
namespace RNChessRulesEngine
{
	/// <summary>
	/// This class defines an object that provides a disconnected database for recording chess moves
	/// that can be used as a datasource for populating a ListBox or DataGrid.
	/// </summary>
	/// <remarks>
	/// This is a work-in-progress.  It should not be used until finalized.
	/// </remarks>
	public class ChessMovesRecorder
	{
		private DataTable _ChessMovesDT = new DataTable("ChessMovesDataTable");
		private DataSet _ChessMovesDS = new DataSet("ChessMovesDataSet");
		private DataRow _currentRow = null;
		private const int TABLE_COLS = 3;
		private const int COL_MVNUM = 0;
		private const int COL_WMOVE = 1;
		private const int COL_BMOVE = 2;
		private int _fullMoveCount = 1;
		private PlayerTurn _movePly = PlayerTurn.White;

		#region Property Accessors
		/// <summary>
		/// Gets the dataset for recorded moves.
		/// </summary>
		public DataSet MovesDataSet
		{
			get { return _ChessMovesDS; }
		}

		/// <summary>
		/// Get/set the current side for recording moves.
		/// </summary>
		public PlayerTurn MovePly
		{
			get { return _movePly; }
			set { _movePly = value; }
		}
		#endregion

		/// <summary>
		/// Constructs a new ChessMovesRecorder.
		/// </summary>
		public ChessMovesRecorder()
		{
			_ChessMovesDS.Tables.Add(_ChessMovesDT);
			BuildMovesTableCols();
			DataView dv = new DataView(_ChessMovesDT);
		}

		#region Public Access Methods
		/// <summary>
		/// Adds a player's move to the current record in the database according to the current MovePly or color that
		/// they are using.
		/// </summary>
		/// <param name="moveSANString">Player move in SAN notation.</param>
		public void AddMove(string moveSANString)
		{			
			// Add row if needed
			if(_currentRow==null) _currentRow = _ChessMovesDT.NewRow();
			
			switch(_movePly)
			{
				case PlayerTurn.White:	// White is always the first ply for a full move.
					_currentRow[COL_WMOVE] = moveSANString;
					_currentRow[COL_MVNUM] = _fullMoveCount;
					break;

				case PlayerTurn.Black:	// Black is always the last ply for a full move.
					_currentRow[COL_BMOVE] = moveSANString;
					_ChessMovesDT.Rows.Add(_currentRow);

					// Add a new row to the table
					_fullMoveCount++;
					_currentRow = _ChessMovesDT.NewRow();
					
					break;
			}

			// Switch sides
			_movePly = (_movePly==PlayerTurn.White ? PlayerTurn.Black : PlayerTurn.White);
		}

		/// <summary>
		/// Retracts the last half-move from the database.
		/// </summary>
		public void RetractLastMove()
		{
			if(_fullMoveCount==1) return;
			switch(_movePly)
			{
				case PlayerTurn.White:
					if((string)_currentRow[COL_WMOVE] == "" && (string)_currentRow[COL_BMOVE] == "")
					{
						_ChessMovesDT.Rows.Remove(_ChessMovesDT.Rows[_ChessMovesDT.Rows.Count]);
						_currentRow = _ChessMovesDT.Rows[_ChessMovesDT.Rows.Count];
						_fullMoveCount--;
						_movePly = PlayerTurn.Black;
					}
					else
					{
						_currentRow[COL_WMOVE] = "";
					}
					break;

				case PlayerTurn.Black:
					if((string)_currentRow[COL_BMOVE] == "")
					{
						_movePly = PlayerTurn.White;
					}
					else
					{
						_currentRow[COL_BMOVE] = "";
					}
					break;
			}
		}

		/// <summary>
		/// Resets the database to its default state.
		/// </summary>
		public void Reset()
		{
			_ChessMovesDT = new DataTable("ChessMovesDataTable");
			_ChessMovesDS = new DataSet("ChessMovesDataSet");
			_ChessMovesDS.Tables.Add(_ChessMovesDT);
			BuildMovesTableCols();
			_movePly = PlayerTurn.White;
			_fullMoveCount = 1;
			_currentRow = null;
		}

		#endregion

		#region Record Construction Methods

		#endregion

		#region Table Construction Methods
		/// <summary>
		/// Builds the columns for the moves table.
		/// </summary>
		private void BuildMovesTableCols()
		{
			// Create columns for tracking chess moves
			for(int col=0; col<TABLE_COLS; col++)
			{
				switch(col)
				{
					case COL_MVNUM:
						_ChessMovesDT.Columns.Add("col_mvnum",Type.GetType("System.Int32"));
						break;
					case COL_WMOVE:
						_ChessMovesDT.Columns.Add("col_wmove",Type.GetType("System.String"));
						break;
					case COL_BMOVE:
						_ChessMovesDT.Columns.Add("col_bmove",Type.GetType("System.String"));
						break;
				}
			}

			// Set up the primary key for the table...
			_ChessMovesDT.PrimaryKey = new DataColumn[] { _ChessMovesDT.Columns[COL_MVNUM] };

		}
		#endregion
	}
}
